﻿using System;
using System.Text;

namespace RFIDMifare
{
    public class RFIDMifare522Utils
    {
        /// <summary>
        /// 将16进制字符串格式化为Byte类型的数组
        /// </summary>
        /// <param name="hexs"></param>
        /// <returns></returns>
        public static byte[] HexStringToByteArray(string hexs)
        {
            string s = hexs.Replace(" ", "");   //去除空格字符
            byte[] vs = new byte[s.Length / 2];

            //将每个两个字符转为byte
            for (int i = 0; i < vs.Length; i++)
            {
                vs[i] = Convert.ToByte(s.Substring(i * 2, 2), 16);
            }

            return vs;
        }

        /// <summary>
        /// Byte数组转String
        /// </summary>
        /// <param name="array"></param>
        /// <param name="spacer">间隔符号</param>
        /// <returns></returns>
        public static string ByteArrayToString(byte[] array, string spacer = "")
        {
            //计算array+间隔符号之后大概需要的字节数
            int initSize = array.Length * spacer.Length + array.Length * 2;
            //创建StringBuilder对象，用于字符串操作（它相较于直接用String对象操作字符串更加快速）
            StringBuilder builder = new StringBuilder(initSize);

            //将array中的每个byte与间隔符好拼接后合并到StringBuilder对象中
            for (int i = 0; i < array.Length; i++)
            {
                //将byte填充到StringBuilder对象中。并一个byte站两个位置，不够两个位置前面用0补齐
                builder.AppendFormat("{0:X2}", array[i]);

                //最后一个字符后面不需要添加间隔符
                if (i != array.Length - 1)
                {
                    builder.Append(spacer);
                }
            }

            return builder.ToString();
        }


        /// <summary>
        /// 计算BCC码
        /// </summary>
        /// <returns></returns>
        public static byte BCCCodeCalculation(byte[] vs)
        {

            byte bcc = 0x00;

            //计算BCC码
            for (int i = 0; i < vs.Length; i++)
            {
                bcc ^= vs[i];
            }
            bcc = (byte)~bcc;

            return bcc;
        }

        /// <summary>
        /// 计算BCC码
        /// </summary>
        /// <param name="vs"></param>
        /// <param name="len">从下标0开始向后开始数，要计算的个数</param>
        /// <returns></returns>
        public static byte BCCCodeCalculation(byte[] vs, int len)
        {

            byte bcc = 0x00;

            //计算BCC码
            for (int i = 0; i < len; i++)
            {
                //异或运算
                bcc ^= vs[i];
            }
            //最后按位取反
            bcc = (byte)~bcc;

            return bcc;
        }

        /// <summary>
        /// int数值转成4字节数组
        /// 从左到右 由低位到高位
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte[] ValueTo4Byte(int value)
        {

            byte[] values = new byte[4];
            for (int i = 0; i < values.Length; i++)
            {
                if (value != 0)
                {
                    values[i] = Convert.ToByte(value & 0xFF);
                    value >>= 8;
                }
                else
                {
                    values[i] = 0;
                }
            }

            return values;
        }

        /// <summary>
        /// int数值转成4字节数组 可选长度
        /// 从左到右 由低位到高位
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte[] ValueTo4Byte(int value, int length)
        {

            byte[] values = new byte[length];
            for (int i = 0; i < values.Length; i++)
            {
                if (value != 0)
                {
                    values[i] = Convert.ToByte(value & 0xFF);
                    value >>= 8;
                }
                else
                {
                    values[i] = 0;
                }
            }

            return values;
        }

        /// <summary>
        /// int数值转块数据
        /// 根据NXP值标准转换
        /// </summary>
        /// <param name="value">要转换的值</param>
        /// <param name="block">指定写入的块号</param>
        /// <returns></returns>
        public static byte[] ValueToBlockData(int value, int block)
        {
            //一个数据块对应一个数值
            //左到右 = 低位到高位
            //一个数值其实只占4个字节
            //但是数值要保存三次 从左往右存 第一次原码(0-3字节) 第二次反码(4-7字节) 第三次原码(8-11字节)
            //剩下4字节用于保存一个块号，表示备份数据的地址，这剩下的4字节中保存四次块号 第一次原块号 第二次取反 第三次原块号 第四次取反
            //如果没有备份地址就写当前的块号

            byte[] values = ValueTo4Byte(value);

            //数值编码
            byte[] valueCode = new byte[16];
            for (int i = 0; i < 4; i++)
            {
                valueCode[i] = values[i];
            }
            for (int i = 0; i < 4; i++)
            {
                valueCode[4 + i] = (byte)~values[i];
            }
            for (int i = 0; i < 4; i++)
            {
                valueCode[8 + i] = values[i];
            }

            //备份地址编码
            for (int i = 0; i < 4; i++)
            {
                if (i % 2 == 0)
                {
                    valueCode[12 + i] = Convert.ToByte(block);
                }
                else
                {
                    valueCode[12 + i] = (byte)~block;
                }
            }

            return valueCode;
        }

        /// <summary>
        /// 块数据转数值
        /// </summary>
        /// <param name="blockData"></param>
        /// <returns></returns>
        public static int BlockDataToValue(byte[] blockData)
        {
            int value = 0;
            for (int i = 0; i < 4; i++)
            {
                value |= blockData[i] << (i * 8);
            }

            return value;
        }

        /// <summary>
        /// 块数据转数值可选长度
        /// </summary>
        /// <param name="blockData"></param>
        /// <returns></returns>
        public static int BlockDataToValue(byte[] blockData ,int length)
        {
            int value = 0;
            for (int i = 0; i < length; i++)
            {
                value |= blockData[i] << (i * 8);
            }

            return value;
        }

        /// <summary>
        /// 字符串转换为16进制字符
        /// </summary>
        /// <param name="s"></param>
        /// <param name="encode"></param>
        /// <returns></returns>
        public static string StringToHexString(string s)
        {
            byte[] b = Encoding.GetEncoding("gb2312").GetBytes(s);//按照指定编码将string编程字节数组
            string result = string.Empty;
            for (int i = 0; i < b.Length; i++)//逐字节变为16进制字符
            {
                result += Convert.ToString(b[i], 16);
            }
            return result;
        }

        /// <summary>
        /// 16进制字符转换为字符串
        /// </summary>
        /// <param name="hs"></param>
        /// <param name="encode"></param>
        /// <returns></returns>
        public static string HexStringToString(string hs)
        {
            string strTemp = "";
            byte[] b = new byte[hs.Length / 2];
            for (int i = 0; i < hs.Length / 2; i++)
            {
                strTemp = hs.Substring(i * 2, 2);
                b[i] = Convert.ToByte(strTemp, 16);
            }
            //按照指定编码将字节数组变为字符串
            return Encoding.GetEncoding("gb2312").GetString(b);
        }
    }
}
